import pandas as pd
import matplotlib.pyplot as plt

# 读取数据（强制所有配置参数作为字符串读取）
df = pd.read_csv('res.txt', comment='#', header=None, 
                names=['p_orig', 'p_sol', 'p_filter', 'pf_orig', 'outer', 'inner',
                       'Cycle', 'avg_power', 'total_area'], 
                sep=',\s*', engine='python', dtype=str)

# 清理数据：移除所有小数点（如100.0 -> 100）
config_cols = ['p_orig', 'p_sol', 'p_filter', 'pf_orig', 'outer', 'inner']
df[config_cols] = df[config_cols].apply(lambda x: x.str.replace(r'\.0$', '', regex=True))

# 数值列转换
num_cols = ['Cycle', 'avg_power', 'total_area']
df[num_cols] = df[num_cols].apply(pd.to_numeric)

# 修正后的编码函数
def encode_config(row):
    parts = [
        f"{row['p_orig']:0>3}",  # 左侧补零到3位
        f"{row['p_sol']:0>2}",
        f"{row['p_filter']:0>2}",
        f"{row['pf_orig']:0>3}",
        f"{row['outer']:0>3}",
        f"{row['inner']:0>3}"
    ]
    binary_str = ''.join(parts)
    return hex(int(binary_str, 2))[2:].upper().zfill(4)  # 补零到4位十六进制

df['config_code'] = df.apply(encode_config, axis=1)

# 归一化计算（保持不变）
metrics = ['Cycle', 'avg_power', 'total_area']
mins = df[metrics].min()
maxs = df[metrics].max()

df['Cycle_norm'] = (df['Cycle'] - mins['Cycle']) / (maxs['Cycle'] - mins['Cycle'])
df['Power_norm'] = (df['avg_power'] - mins['avg_power']) / (maxs['avg_power'] - mins['avg_power'])
df['Area_norm'] = (df['total_area'] - mins['total_area']) / (maxs['total_area'] - mins['total_area'])

# 综合评分计算
alpha, beta, gamma = 0.5, 0.25, 0.25
df['Score'] = (alpha * df['Cycle_norm'] + 
              beta * df['Power_norm'] + 
              gamma * df['Area_norm'])

# 输出结果
print("Processed Data:")
print(df[['config_code'] + metrics + ['Score']].to_string(index=False))

# 可视化（改进版）
plt.figure(figsize=(15, 6))
plt.scatter(df['config_code'], df['Score'], 
            c=df['Score'], cmap='RdYlGn',  # 红-黄-绿色阶
            s=10, alpha=0.7, edgecolor='k')

plt.colorbar(label='score')
plt.xticks(rotation=90, fontsize=8)
plt.xlabel('Configuration Code (Hex)')
plt.ylabel('Normalized Score')
plt.title('Stencil Design Space Exploration\n'
         f'Weighting: Cycle={alpha}, Power={beta}, Area={gamma}')

# 自动调整显示密度
if len(df) > 20:
    plt.gca().set_xticks(plt.gca().get_xticks()[::len(df)//20])

#  Annotate the best configuration (minimum score)
# 找出评分最低的配置
min_score_row = df.loc[df['Score'].idxmin()]

# 添加标注（使用红色突出显示）
plt.annotate(
    f"best: {min_score_row['config_code']}\nScore={min_score_row['Score']:.3f}",
    xy=(min_score_row['config_code'], min_score_row['Score']),
    xytext=(20, -30),  # 文本偏移量
    textcoords='offset points',
    arrowprops=dict(arrowstyle="->", color='red'),
    bbox=dict(boxstyle='round,pad=0.5', fc='white', alpha=0.8),
    color='red',
    fontsize=10
)

# 在最低分点上添加红色标记
plt.scatter(
    [min_score_row['config_code']],
    [min_score_row['Score']],
    color='red',
    s=40,  # 放大标记点
    edgecolors='black',
    linewidths=1.5,
    zorder=10  # 确保在最上层
)

plt.grid(True, linestyle=':', alpha=0.5)
plt.tight_layout()
plt.savefig('results.png', dpi=300)
print("\nVisualization saved to results.png")